package com.puhui.lib.widgets

import android.content.Context
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.text.*
import android.text.method.LinkMovementMethod
import android.text.style.AbsoluteSizeSpan
import android.text.style.ClickableSpan
import android.text.style.ForegroundColorSpan
import android.text.style.UnderlineSpan
import android.widget.EditText
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.annotation.IntDef
import androidx.core.content.ContextCompat
import com.puhui.lib.BuildConfig
import com.puhui.lib.utils.ToastUtil

class TextViewUtils {

    companion object {
        /**
         * 给部分文字设置颜色
         *
         * setSpan()的最后一个参数为布尔型，可以传入以下四种：
         * Spanned.SPAN_INCLUSIVE_EXCLUSIVE 从起始下标到终止下标，包括起始下标
         * Spanned.SPAN_INCLUSIVE_INCLUSIVE 从起始下标到终止下标，同时包括起始下标和终止下标
         * Spanned.SPAN_EXCLUSIVE_EXCLUSIVE 从起始下标到终止下标，但都不包括起始下标和终止下标
         * Spanned.SPAN_EXCLUSIVE_INCLUSIVE 从起始下标到终止下标，包括终止下标
         */
        fun setPartTextColor(textView: TextView, content: String?, start: Int, end: Int, color: Int) {
            if (TextUtils.isEmpty(content)) return
            val spannableString = SpannableString(content)
            spannableString.setSpan(ForegroundColorSpan(color), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
            textView.text = spannableString
        }

        /**
         * 改变部分文字大小
         */
        fun changePartTextSize(textView: TextView, content: String?, start: Int, end: Int, size: Int) {
            if (TextUtils.isEmpty(content)) return
            val sp: Spannable = SpannableString(content)
            sp.setSpan(AbsoluteSizeSpan(size, true), start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
            textView.text = sp
        }

        /**
         * 改变部分文字大小
         */
        fun changePartTextSize(textView: TextView, content: String?, vararg textStyles: TextStyle) {
            if (TextUtils.isEmpty(content)) return
            val sp: Spannable = SpannableString(content)
            try {
                for (textStyle in textStyles) {
                    sp.setSpan(
                        AbsoluteSizeSpan(textStyle.size, true),
                        textStyle.start, textStyle.end, Spannable.SPAN_INCLUSIVE_INCLUSIVE
                    )
                }
                textView.text = sp
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        data class TextStyle constructor(
            val size: Int,
            val color: Int = 0,
            val start: Int = 0,
            val end: Int = 0
        )

        /**
         * 改变部分文字大小 和 颜色
         */
        fun changeSizeAndColor(textView: TextView, content: String?, start: Int, end: Int, size: Int, color: Int) {
            val spannableString: Spannable = SpannableString(content)
            spannableString.setSpan(ForegroundColorSpan(color), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
            spannableString.setSpan(AbsoluteSizeSpan(size, true), start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
            textView.text = spannableString
        }

        fun getTextHeight(paint: Paint): Float {
            val fontMetricsInt = paint.fontMetricsInt
            return (fontMetricsInt.descent - fontMetricsInt.ascent).toFloat()
        }

        fun getTextWidth(paint: Paint, text: String): Int {
            val rect = Rect()
            paint.getTextBounds(text, 0, text.length, rect)
            return rect.width() //rect.height();
        }

        fun setClickSpan(
            textView: TextView, source: String, @ColorInt foregroundColor: Int,
            start: Int, end: Int, clickableSpan: ClickableSpan?
        ) {
            if (start >= end) return
            if (start > source.length || end > source.length) {
                if (BuildConfig.DEBUG) ToastUtil.showToast("setClickSpan 数组越界")
                return
            }
            val spannableInfo = SpannableString(source)
            spannableInfo.setSpan(ForegroundColorSpan(foregroundColor), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
            spannableInfo.setSpan(clickableSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
            spannableInfo.setSpan(object : UnderlineSpan() {
                override fun updateDrawState(ds: TextPaint) {
                    super.updateDrawState(ds)
                    ds.color = foregroundColor
                    ds.isUnderlineText = false // 去掉下划线
                }
            }, start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
            textView.movementMethod = LinkMovementMethod.getInstance()
            textView.highlightColor = Color.TRANSPARENT
            textView.text = spannableInfo
        }

        /**
         * 设置drawable为空
         */
        fun cancelDrawable(textView: TextView) {
            textView.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
        }

        /**
         * set TextView DrawableLeft or DrawableRight
         */
        fun setTvDrawable(context: Context?, @DrawableRes resourceId: Int, textView: TextView, @Direction.Model direction: Int) {
            // 可用setCompoundDrawablesWithIntrinsicBounds方法
            try {
                val drawable = ContextCompat.getDrawable(context!!, resourceId)
                if (null != drawable) {
                    drawable.setBounds(0, 0, drawable.minimumWidth, drawable.minimumHeight)
                    when (direction) {
                        Direction.LEFT -> textView.setCompoundDrawables(drawable, null, null, null)
                        Direction.RIGHT -> textView.setCompoundDrawables(null, null, drawable, null)
                        Direction.TOP -> textView.setCompoundDrawables(null, drawable, null, null)
                        Direction.BOTTOM -> textView.setCompoundDrawables(null, null, null, drawable)
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        /**
         * 密码输入框内容密码是可见还是不可见
         *
         * @param isShowPwd true 可见； false 不可见
         */
        fun showOrHintEditTextPwd(editText: EditText, isShowPwd: Boolean) {
            showOrHintEditTextPwd(editText, isShowPwd, false)
        }

        /**
         * 密码输入框内容密码是可见还是不可见
         *
         * @param isShowPwd true 可见； false 不可见
         */
        fun showOrHintEditTextPwd(editText: EditText, isShowPwd: Boolean, isNumberPwd: Boolean) {
            if (isShowPwd) {
                //选择状态 显示明文--设置为可见的密码
                if (isNumberPwd) {
                    editText.inputType = InputType.TYPE_CLASS_NUMBER
                } else {
                    editText.inputType = InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
                }
            } else {
                //隐藏密码 要一起写才能起作用 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD
                if (isNumberPwd) {
                    editText.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
                } else {
                    editText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
                }
            }
            editText.setSelection(editText.length())
        }

        /**
         * 判断TextView设置的文字内容是否全部显示了
         */
        fun haveTextShowAll(textView: TextView): Boolean {
            val layout = textView.layout
            val lineCount = layout.lineCount
            return if (lineCount > 0) {
                if (lineCount > textView.maxLines) {
                    //如果测量的lineCount 超过了 maxLines 文字没有完全展示
                    false
                } else {
                    //没有超过maxLines 看省略号的位置
                    layout.getEllipsisCount(lineCount - 1) <= 0
                }
            } else {
                true
            }
        }
    }

    class Direction {
        companion object {
            const val LEFT = 1
            const val RIGHT = 1 shl 1
            const val TOP = 3
            const val BOTTOM = 1 shl 2
        }

        //flag值为true的话，则表示只能取value里面的一个值；false表示能取value里的多个值，用或符号“|”连接
        @IntDef(flag = true, value = [LEFT, RIGHT, TOP, BOTTOM])
        @Retention(AnnotationRetention.SOURCE)
        @Target(AnnotationTarget.VALUE_PARAMETER)
        internal annotation class Model
    }
}